from Common.EventHandle import EventHandle

from Calendar.Calendar import *
from Misc.QuoteType import *
from Misc.FinRType import *
from FinancialAsset.AssetFactory import *

from DataFeeder.QueryFundTopHolding import *
from DataFeeder.QueryFinancialRatio import *
from DataFeeder.QueryQuote import *

from datetime import date


class PESort(EventHandle):
	
	def __init__(self, start_date, end_date, stock_size, is_small = True):
	
		self.stock_size = stock_size
		self.is_small = is_small
		
		cld = TradingCalendar()
		data_dates = cld.date_series(start_date, end_date, Frequency.Annual)
		
		EventHandle.__init__(self, data_dates)
		
	def create_activities(self, ref_date, portf = None):
	
		print 'running info...', ref_date.isoformat()

		holding = portf.holding(ref_date)
		print '   step 1, acquring holding completed...', len(holding)
		
		nav = portf.nav(ref_date)
		print '   step 2, acquring nav completed...', nav
		
		#fund holding
		d = date(ref_date.year-1, 12, 31) if ref_date.month < 12 else ref_date
		fund_holding = query_fund_top_holding(d)
		
		stock_pool = set()
		for k in fund_holding.keys():
			stock_pool.add(k[1])
				
		print '   step 3, acquring fund holding completed...', len(stock_pool)
		
		#pe dict
		fr_dict = query_financial_ratio(ref_date, list(stock_pool))
		pe = {}
		for stock_tick in stock_pool:
		
			eps = fr_dict[stock_tick][FinRType.EPS] if fr_dict.has_key(stock_tick) else None
			close = QuoteRegister().get_stock_quote(ref_date, stock_tick, QuoteType.CLOSE)
			
			if eps and close and eps > 0 and close > 0:
				pe[stock_tick] = close / eps
		
		#stock pool
		pe = sorted(pe.iteritems(), key=lambda pe:pe[1], reverse=(not self.is_small))
		
		pe_pool = set()
		for i in range(self.stock_size):
			pe_pool.add(AssetFactory().acquire_asset('STOCK', pe[i][0]))
		
		print '   step 4, acquring stock pool completed...', len(pe_pool)
		
		activities = []
		
		for sec, quantity in holding.iteritems():
			if sec.type_name() == 'STOCK':
				
				close = QuoteRegister().get_stock_quote(ref_date, sec.ticker(), QuoteType.CLOSE)
				cash = AssetFactory().acquire_asset('CASH', sec.currency())
				
				activities.append((ref_date, sec, -quantity))
				activities.append((ref_date, cash, quantity*close))
		
		for sec in pe_pool:
			
			close = QuoteRegister().get_stock_quote(ref_date, sec.ticker(), QuoteType.CLOSE)
			
			if close and close > 0:
				cash = AssetFactory().acquire_asset('CASH', sec.currency())
				quantity = int(nav/len(pe_pool)/close)
				
				activities.append((ref_date, sec, quantity))
				activities.append((ref_date, cash, -quantity*close))
			
		print '   step 5, create activies completed...', len(activities)
		
		return activities
		
	@staticmethod	
	def event_name():
		return 'PESort'